# [generateMetadata](https://nextjs.org/docs/app/api-reference/functions/generate-metadata 'generateMetadata')

## Metadata Object and generateMetadata Options

本文涵盖了所有基于 **Config-based Metadata** 选项，包括 **generateMetadata** 和 **metadata** 对象

```
import { Metadata } from 'next'

// either Static metadata
export const metadata: Metadata = {
  title: '...',
}

// or Dynamic metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}
```

```
1. Metadata 和 generateMetadata 函数到处仅在服务器组件中支持
2. 不能同时导出 Metadata 和 generateMetadata 函数
```

## Metadata 对象

要定义静态的 metadata ，请从layout.js 或 page.js 文件中导出 metadata 对象

```
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: '...',
  description: '...',
}

export default function Page() {}
```

## generateMetadata 函数

动态元素据依赖动态信息，例如当前路由 generateMetadata 函数返回一个元素据对象。参数、外部数据或父段中的元数据可以通过导出

```
import { Metadata, ResolvingMetadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = params.id

  // fetch data
  const product = await fetch(`https://.../${id}`).then((res) => res.json())

  // optionally access and extend (rather than replace) parent metadata
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}

export default function Page({ params, searchParams }: Props) {}
```

## 参数

generateMetadata 函数接收以下参数 props - 包含当前路由参数的对象

-- params 一个对象，包含从根节点到 generateMetadata 被调用的动态参数对象

![params](/assets/images/generateMetadata-params.png 'params')

-- searchParams 一个包含当前 URL 搜索参数的对象

![searchParams](/assets/images/generateMetadata-searchParams.png 'searchParams')

## Returns

generateMetadata 应该返回一个包含一个或多个元数据字段的元数据对象

## Metadata 字段

#### title

title 属性用于设置文档的标题。它可以定义为一个简单的字符串或一个可选的模板对象

```
export const metadata = {
  title: 'Next.js',
}
```

#### Template 对象

```
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '...',
    default: '...',
    absolute: '...',
  },
}
```

#### Default

title.default 可以用来为没有定义标题的子路由提供一个备用标题。

```
app/layout.tsx

import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    default: 'Acme',
  },
}
```

```
app/about/page.tsx

import type { Metadata } from 'next'

export const metadata: Metadata = {}

// Output: <title>Acme</title>
```

#### Template

title.template 可以用来为子路由中定义的标题添加后缀

```
app/layout.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
    default: 'Acme', // a default is required when creating a template
  },
}
```

```
app/about/page.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'About',
}

// Output: <title>About | Acme</title>
```

#### Absolute

title.absolute 可用于提供忽略 title.template。

```
app/layout.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
  },
}
```

```
app/about/page.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    absolute: 'About',
  },
}

// Output: <title>About</title>
```

#### description

```
layout.js | page.js

export const metadata = {
  description: 'The React Framework for the Web',
}
```

```
<head> output

<meta name="description" content="The React Framework for the Web" />
```

## 基本字段

```
layout.js | page.js

export const metadata = {
  generator: 'Next.js',
  applicationName: 'Next.js',
  referrer: 'origin-when-cross-origin',
  keywords: ['Next.js', 'React', 'JavaScript'],
  authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
  creator: 'Jiachi Liu',
  publisher: 'Sebastian Markbåge',
  formatDetection: {
    email: false,
    address: false,
    telephone: false,
  },
}
```

```
<head> output

<meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />
```

#### metadataBase

metadataBase 是一个方便的选项，可以为需要完全限定 URL 的 metadata 字段设置基本的 URL 前缀

- metadataBase 允许当前路由及以下定义的 URL 的元素据使用相对路径，而不是绝对路径

- 字段的相对路径将与 metadataBase 组成完全限定的 URL

- 如果没有配置，则使用默认自动填充 metadataBase 当前环境地址 也可以配置 process.env

- 如果 metadata 字段提供了绝对的 URL ，则 metadataBase 将被忽略

```
layout.js | page.js

export const metadata = {
  metadataBase: new URL('https://acme.com'),
  alternates: {
    canonical: '/',
    languages: {
      'en-US': '/en-US',
      'de-DE': '/de-DE',
    },
  },
  openGraph: {
    images: '/og-image.png',
  },
}
```

```
<head> output

<link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />
```

#### URL Composition

URL 组合比默认的路径更有利于开发人员的意图

- metadataBase 和 metadata 之间的尾斜杠规范化
- metadata 字段中的绝对路径（通常会取代整个 URL 路径）被视为“相对”路径（从 metadataBase 的末尾开始）

```
app/layout.tsx

import { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://acme.com'),
}
```

任何 metadata 字段设置自己的 metadataBase 字段将被解析如下：

```
/	                              https://acme.com
./	                            https://acme.com
payments	                      https://acme.com/payments
/payments	                      https://acme.com/payments
./payments	                    https://acme.com/payments
../payments	                    https://acme.com/payments
https://beta.acme.com/payments	https://beta.acme.com/payments
```

## openGraph

```
layout.js | page.js

export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png', // Must be an absolute URL
        width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png', // Must be an absolute URL
        width: 1800,
        height: 1600,
        alt: 'My custom alt',
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}
```

```
<head> output

<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="My custom alt" />
<meta property="og:type" content="website" />
```

```
layout.js | page.js

export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    type: 'article',
    publishedTime: '2023-01-01T00:00:00.000Z',
    authors: ['Seb', 'Josh'],
  },
}
```

```
<head> output

<meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />
```

很高兴知道:对于Open Graph图像使用基于文件的元数据API可能更方便。无需将配置导出与实际文件同步，基于文件的API将自动为您生成正确的元数据。

## robots

```
import type { Metadata } from 'next'

export const metadata: Metadata = {
  robots: {
    index: false,
    follow: true,
    nocache: true,
    googleBot: {
      index: true,
      follow: false,
      noimageindex: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
}
```

```
<head> output

<meta name="robots" content="noindex, follow, nocache" />
<meta
  name="googlebot"
  content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
```
